package com.example.demo;

import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.retailcloud.model.v20180313.ListAppEnvironmentRequest;
import com.aliyuncs.retailcloud.model.v20180313.ListAppEnvironmentResponse;
import com.aliyuncs.retailcloud.model.v20180313.ListAppInstanceRequest;
import com.aliyuncs.retailcloud.model.v20180313.ListAppInstanceResponse;
import com.aliyuncs.retailcloud.model.v20180313.ListAppRequest;
import com.aliyuncs.retailcloud.model.v20180313.ListAppResponse;
import java.lang.reflect.Field;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author lizhien (zhien.li@nascent.cn)
 * @version 1.0.0
 * @date 2022/3/18 16:02
 * @description com.example.demo
 */

@RestController
@Slf4j
@EnableCaching
@EnableScheduling
@RequestMapping(value = "/prometheus")
public class PrometheusJSTController {

    private final Lock lock = new ReentrantLock();

    @RequestMapping(value = "/jst", produces = "text/plain;charset=utf-8")
    @Cacheable(cacheNames = "jstListApp")
    public String jstListApp() throws InterruptedException {
        String list = "jst_app_env_pod_info{lock=\"1\"} 0";
        if (lock.tryLock(1, TimeUnit.SECONDS)) {
            try {
                list = listApp();
            } finally {
                lock.unlock();
            }
        }
        return list;
    }

    @RequestMapping(value = "/clearCache")
    @CacheEvict(cacheNames = "jstListApp", allEntries = true, beforeInvocation = true)
    public String clearCache() {
        log.info("cache clear.");
        return "ok";
    }

    @Scheduled(initialDelay = 1000 * 60, fixedRate = 1000 * 60 * 30)
    @CachePut(cacheNames = "jstListApp")
    public synchronized String listApp() {
        StringBuffer sBuffer = new StringBuffer();
        // Create an API request and set parameters
        ListAppRequest request = new ListAppRequest();
        request.setActionName("ListApp");
        request.setPageSize(1000);
        request.setPageNumber(1);
        try {
            // Initiate the request and handle the response or exceptions
            ListAppResponse response = client.getAcsResponse(request);
            log.info("聚石塔应用总数：" + response.getTotalCount());
            for (int i = 0; i < response.getTotalCount(); i++) {
                ListAppResponse.AppDetail appDetail = response.getData().get(i);
                if (appDetail.getTitle().contains("ecrp") || appDetail.getTitle().contains("sca")) {
                    sBuffer.append(listEnv(appDetail.getAppId(), appDetail.getTitle()));
                } else {
                    log.warn("非ECRP应用ID：" + appDetail.getAppId() + ";应用名称：" + appDetail.getTitle());
                }
                if (i > 100) {
                    //break;
                }
            }
        } catch (ClientException e) {
            e.printStackTrace();
        }

        return String.valueOf(sBuffer).replace("'", "\"");
    }

    private static IAcsClient client = new DefaultAcsClient(DefaultProfile.getProfile(
        "cn-zhangjiakou", "LTAI4GCcxm1ZZVQyY5EbP92N", "9DwIzMjNmd4BKaJzu9lQttw66YXfHn"));

    private static String listEnv(Long appId, String appName) {
        // Create an API request and set parameters
        ListAppEnvironmentRequest request = new ListAppEnvironmentRequest();
        request.setActionName("ListAppEnvironment");
        request.setAppId(appId);
        request.setPageSize(1000);
        request.setPageNumber(1);

        StringBuffer sBuffer = new StringBuffer();
        try {
            // Initiate the request and handle the response or exceptions
            ListAppEnvironmentResponse response = client.getAcsResponse(request);
            for (ListAppEnvironmentResponse.AppEnvironmentResponse appDetail : response.getData()) {
                sBuffer.append(listAppInstance(appId, appName, appDetail.getEnvId(), appDetail.getEnvName()));
            }
        } catch (ClientException e) {
            e.printStackTrace();
        }

        return String.valueOf(sBuffer);
    }

    private static String listAppInstance(Long appId, String appName, Long envId, String envName) {
        // Create an API request and set parameters
        ListAppInstanceRequest request = new ListAppInstanceRequest();
        request.setActionName("ListAppInstance");
        request.setAppId(appId);
        request.setEnvId(envId);
        request.setPageSize(1000);
        request.setPageNumber(1);

        StringBuffer sBuffer = new StringBuffer();
        try {
            // Initiate the request and handle the response or exceptions
            ListAppInstanceResponse response = client.getAcsResponse(request);
            for (ListAppInstanceResponse.AppInstanceDetail appDetail : response.getData()) {
                sBuffer.append("jst_app_env_pod_info{appid='" + appId + "',appname='" + appName + "',envid='" + envId + "',envname='" + envName + "',");
                sBuffer.append(getAllFields(appDetail));
                sBuffer.append("} " + System.currentTimeMillis() + "\n");
                log.info(String.valueOf(sBuffer));
            }
        } catch (ClientException e) {
            e.printStackTrace();
        }

        return String.valueOf(sBuffer);
    }

    private static String getAllFields(Object obj) {
        Class cls = obj.getClass();
        Field[] fields = cls.getDeclaredFields();
        StringBuffer sBuffer = new StringBuffer();
        for (Field field : fields) {
            field.setAccessible(true);
            try {
                sBuffer.append(field.getName() + "='" + field.get(obj) + "',");
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        return String.valueOf(sBuffer);
    }
}
